﻿using UnityEngine;
using System;
using System.Collections;
using System.IO;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace GBFramework
{
    public class AssetBundleLoader : MonoBehaviour
    {
        public string[] preloadBundles;
        const string kAssetBundlesPath = "/AssetBundles/";

        //开始场景ab包配置
        [SerializeField]
        public string sceneAssetBundle;
        [SerializeField]
        public string sceneName;
        private string bundlePath = "assets/abres/scene/";
        private bool firstLoaded = false;
        private bool isResPreloaded = false;

        static AssetBundleLoader _instance;
        public static AssetBundleLoader Instance
        {
            get
            {
                return _instance;
            }
            set
            {
                _instance = value;
            }
        }

        void Awake()
        {
            AssetBundleLoader.Instance = this;
            DontDestroyOnLoad(gameObject);
        }

        // Use this for initialization.
        IEnumerator Start()
        {
            yield return StartCoroutine(Initialize());

        }

        void LateUpdate()
        {
            if (AssetBundleManager.m_AssetBundleManifest == null) return;

            GameSpriteCacheManager.Instance().Update();
            GameAssetsCacheManager.Instance().Update();
        }

        // Initialize the downloading url and AssetBundleManifest object.

        public void InitWithCallback(Action cb)
        {
            StartCoroutine(Initialize(cb));
        }

        public IEnumerator Initialize(Action cb = null)
        {
            // Don't destroy the game object as we base on it to run the loading script.

            string platformFolderForAssetBundles =

#if UNITY_EDITOR
 GetPlatformFolderForAssetBundles(EditorUserBuildSettings.activeBuildTarget);

            //Debug.Log("We are " + (AssetBundleManager.SimulateAssetBundleInEditor ? "in Editor simulation mode" : "in normal mode"));
#else
		GetPlatformFolderForAssetBundles(Application.platform);
#endif

            // Initialize AssetBundleManifest which loads the AssetBundleManifest object.
            var request = AssetBundleManager.Initialize(platformFolderForAssetBundles);

            if (request != null)
            {
#if Log_Open
                Debug.Log(" loading  manifest ");
#endif
                yield return StartCoroutine(request);
            }
            else
            {
#if Log_Open
                Debug.Log(" Init error");
#endif
            }
            if (cb != null)
            {
                cb();
            }
        }

        public void preload()
        {
            if (!isResPreloaded)
            {
                for (int i = 0; i < preloadBundles.Length; i++)
                {
                    string bundleName = preloadBundles[i];
                    if (!string.IsNullOrEmpty(bundleName))
                        AssetBundleManager.LoadAssetBundle(preloadBundles[i]);
                }
                isResPreloaded = true;
            }
        }

        public string getBundleUrl(string fileName)
        {
#if UNITY_ANDROID

        string url = Application.dataPath + "/assets" + "/AssetBundles/" + Utility.GetPlatformName() + "/" + fileName;

#else
            string url = Globals.streamingPath + "/AssetBundles/" + Utility.GetPlatformName() + "/" + fileName;
#endif

            if (true)
            {
                string updateDir = Globals.persistenPath + "/AssetBundles/" + Utility.GetPlatformName() + "/" + fileName;

                if (File.Exists(updateDir))
                {
                    //url = "file:///" + updateDir; //www下载时候使用
                    url = updateDir;
                }
            }

            return url.Replace(" ", "%20");
        }


#if UNITY_EDITOR
        public static string GetPlatformFolderForAssetBundles(BuildTarget target)
        {
            switch (target)
            {
                case BuildTarget.Android:
                    return "Android";
                case BuildTarget.iOS:
                    return "iOS";
                case BuildTarget.WebPlayer:
                    return "WebPlayer";
                case BuildTarget.StandaloneWindows:
                case BuildTarget.StandaloneWindows64:
                    return "Windows";
                case BuildTarget.StandaloneOSXIntel:
                case BuildTarget.StandaloneOSXIntel64:
                case BuildTarget.StandaloneOSXUniversal:
                    return "OSX";
                // Add more build targets for your own.
                // If you add more targets, don't forget to add the same platforms to GetPlatformFolderForAssetBundles(RuntimePlatform) function.
                default:
                    return null;
            }
        }
#endif

        static string GetPlatformFolderForAssetBundles(RuntimePlatform platform)
        {
            switch (platform)
            {
                case RuntimePlatform.Android:
                    return "Android";
                case RuntimePlatform.IPhonePlayer:
                    return "iOS";
                case RuntimePlatform.WindowsWebPlayer:
                case RuntimePlatform.OSXWebPlayer:
                    return "WebPlayer";
                case RuntimePlatform.WindowsPlayer:
                    return "Windows";
                case RuntimePlatform.OSXPlayer:
                    return "OSX";
                default:
                    return null;
            }
        }

        #region 异步加载
        public void LoadAssetAsync(string assetBundleName, string assetName, LoadAssetCallBack fn, bool bDestroy = false)
        {

            StartCoroutine(OnLoadAssetAsync(assetBundleName, assetName, fn, bDestroy));
        }

        public IEnumerator OnLoadAssetAsync(string assetBundleName, string assetName, LoadAssetCallBack fn, bool bDestroy)
        {
            AssetBundleLoadAssetOperation request = AssetBundleManager.LoadAssetAsync(assetBundleName, assetName, typeof(UnityEngine.Object));
            if (request == null)
                yield break;
            yield return StartCoroutine(request);

            if (request.isStop)
            {
                yield break;
            }

            UnityEngine.Object obj = request.GetAsset<UnityEngine.Object>();
            //#if Log_Open
            //        SampleDebuger.Log(assetName + (obj == null ? " isn't" : " is") + " loaded successfully at frame " + Time.frameCount);
            //#endif
            if (fn != null)
                fn(obj);
            if (bDestroy)
                AssetBundleManager.UnloadAssetBundle(assetBundleName, true);
        }

        public void LoadAllAssetAsync(string assetBundleName, string assetName, LoadAllAssetCallBack fn)
        {
            StartCoroutine(OnLoadAllAssetAsync(assetBundleName, assetName, fn));
        }

        public IEnumerator OnLoadAllAssetAsync(string assetBundleName, string assetName, LoadAllAssetCallBack fn)
        {
            AssetBundleLoadAssetOperation request = AssetBundleManager.LoadAssetAsync(assetBundleName, assetName, typeof(UnityEngine.Object), false);
            if (request == null)
                yield break;
            yield return StartCoroutine(request);

            if (request.isStop)
                yield break;

            UnityEngine.Object[] obj = request.GetAllAsset<UnityEngine.Object>();
            //#if Log_Open
            //        SampleDebuger.Log(assetName + (obj == null ? " isn't" : " is") + " loaded successfully at frame " + Time.frameCount);
            //#endif
            if (fn != null)
                fn(obj);
            //AssetBundleManager.UnloadAssetBundle(assetBundleName);
        }

        public void LoadLevelAssetAsync(string name, LoadSceneCallBack fn = null)
        {
            string bundle = bundlePath + name;
            int lastIdx = name.LastIndexOf('/');
            string levelName = name;
            if (lastIdx > 0)
                levelName = name.Substring(lastIdx + 1);
            StartCoroutine(LoadLevelAsync(bundle.ToLower(), levelName, fn));
        }

        protected IEnumerator LoadLevelAsync(string assetBundleName, string levelName, LoadSceneCallBack fn)
        {
            //#if Log_Open
            //        SampleDebuger.Log("Start to load scene " + levelName + " at frame " + Time.frameCount);
            //#endif

            // Load level from assetBundle.
            AssetBundleLoadBaseOperation request = AssetBundleManager.LoadLevelAsync(assetBundleName, levelName, false);
            if (request == null)
                yield break;
            yield return StartCoroutine(request);

            if (fn != null)
            {
                AsyncOperation aync = null;
                if (request != null)
                {
                    aync = request.m_sceneRequest;
                }

                if (request.isStop)
                    yield break;
                fn(aync);
            }
            // This log will only be output when loading level additively.
            //Debug.Log("Finish loading scene " + levelName + " at frame " + Time.frameCount);
        }

        #endregion
    }

}